// 改进版 findNodeFlexible，支持自定义比较、深度和节点数限制
// 用于在树形结构中灵活查找节点，并返回节点及其路径
export function findNodeFlexible(
	data,
	field = 'id', // 要匹配的字段名，默认'id'
	value, // 要查找的值
	childFields = ['children', 'steps'], // 可能的子节点字段名
	path = [], // 当前递归路径，调用时不用传
	options = {} // 其他可选参数
) {
	// 参数校验
	if (!Array.isArray(data)) throw new Error('输入数据必须是数组')
	if (typeof field !== 'string' || !field)
		throw new Error('field 参数必须是有效的字符串')
	if (!Array.isArray(childFields)) throw new Error('childFields 参数必须是数组')

	// 解析可选参数
	const {
		maxDepth = 100, // 最大递归深度，防止死循环
		maxNodes = 10000, // 最大遍历节点数，防止超大树卡死
		compareFn = null, // 自定义比较函数
		_nodeCount = { count: 0 }, // 内部计数器，递归时传递
	} = options

	// 超过最大递归深度直接返回
	if (path.length > maxDepth) return null

	// 遍历当前层的每个节点
	for (const item of data) {
		_nodeCount.count++
		// 超过最大节点数直接返回
		if (_nodeCount.count > maxNodes) return null
		if (!item) continue // 跳过无效节点
		const currentPath = [...path, item] // 记录当前路径
		// 判断是否匹配（支持自定义比较）
		const isMatch = compareFn
			? compareFn(item, field, value)
			: item[field] === value
		if (isMatch) {
			// 找到目标节点，返回节点和路径
			return { node: item, path: currentPath }
		}
		// 递归查找所有可能的子节点字段
		for (const childField of childFields) {
			if (item[childField] && Array.isArray(item[childField])) {
				const result = findNodeFlexible(
					item[childField],
					field,
					value,
					childFields,
					currentPath,
					{ maxDepth, maxNodes, compareFn, _nodeCount }
				)
				if (result) return result // 找到就返回
			}
		}
	}
	// 没找到返回 null
	return null
}

// 便捷函数：自定义比较
// compareFn: (item, field, value) => boolean
export function findNodeWithCustomCompare(
	data,
	field,
	value,
	childFields = ['children', 'steps'],
	compareFn,
	path = [],
	options = {}
) {
	return findNodeFlexible(data, field, value, childFields, path, {
		...options,
		compareFn,
	})
}

// 便捷函数：限制深度
export function findNodeWithDepthLimit(
	data,
	field,
	value,
	childFields = ['children', 'steps'],
	maxDepth = 50,
	path = [],
	options = {}
) {
	return findNodeFlexible(data, field, value, childFields, path, {
		...options,
		maxDepth,
	})
}
